Skip to content

Fix misleading notification when admin self-delete is rejected#1357

Open
MatusBeke wants to merge 1 commit into
dtq-devfrom
fix/eperson-delete-self-notification
Open

Fix misleading notification when admin self-delete is rejected#1357
MatusBeke wants to merge 1 commit into
dtq-devfrom
fix/eperson-delete-self-notification

Conversation

@MatusBeke

@MatusBeke MatusBeke commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Problem

When an admin's own-account delete request is rejected by the backend, the frontend was supposed to show a friendly "you cannot delete your own account" message. It sometimes didn't, and fell through to the generic, technical failure notification instead.

Root cause

EPersonDeleteGuardService.isSelfDeletionError() detects the backend rejection by pattern-matching the response's error text against "cannot delete yourself". That text is not reliably present:

  • Spring Boot omits exception message fields from error response bodies by default (server.error.include-message defaults to never).
  • DSpaceBadRequestException / IllegalStateException have no dedicated @ExceptionHandler that builds a structured JSON body with the message.

So a legitimate self-delete rejection can arrive with no usable message text, the pattern match silently fails, and the UI falls through to the generic "delete failed" notification instead of the friendly self-delete one.

Fix

Add a deterministic client-side identity check (isCurrentUser) as an OR-fallback alongside the text match, in both delete entry points (EPeople registry list and the individual EPerson edit form). This doesn't depend on what the backend's error body contains — if we already know the target is the current user, we show the friendly message regardless.

Test plan

  • yarn run lint — passes
  • circular dependency check — passes
  • yarn run test:headless — full suite (5465 tests) passes, including 2 new regression tests simulating a race where the auth-subscription resolves late and the backend rejection carries no matchable message
  • yarn run build:prod — succeeds
  • Verified against a live DSpace stack (Docker) that the backend's actual self-delete rejection format is reproduced by the new tests

Fixes dataquest-dev/dspace-customers#782

Summary by CodeRabbit

  • Bug Fixes
    • Improved delete error handling so self-delete attempts now consistently show the friendly “you can’t delete yourself” message, even when the backend response doesn’t include a usable error message.
    • Applied this behavior in both the registry and form flows.
  • Tests
    • Added coverage for delayed user identity resolution to ensure the self-delete notification still appears instead of a generic failure message.
  • Documentation
    • Clarified the guidance for detecting self-delete errors.

…or text

isSelfDeletionError() matches the backend's rejection message as plain text,
but Spring Boot omits exception messages from error response bodies by
default and DSpaceBadRequestException/IllegalStateException have no
dedicated JSON-body exception handler, so the match can silently fail and
fall through to the generic, unfriendly failure notification instead of the
"you cannot delete your own account" one. Add a deterministic client-side
identity check as a fallback alongside the text match so the friendly
message shows reliably regardless of what the backend's error body contains.

Fixes dataquest-dev/dspace-customers#782

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Delete-failure handling in EPeopleRegistryComponent and EpersonFormComponent now shows the self-delete notification when the target equals the current user, in addition to the prior error-message-based check. Guard documentation was updated to reflect this fallback rationale, and new spec tests cover late-resolved user id scenarios.

Changes

Self-delete notification fix

Layer / File(s) Summary
Guard documentation update
src/app/access-control/epeople-registry/eperson-delete-guard.service.ts
JSDoc for isSelfDeletionError clarified as a best-effort fallback since Spring Boot often omits exception messages.
Epeople registry self-delete branch and tests
src/app/access-control/epeople-registry/epeople-registry.component.ts, src/app/access-control/epeople-registry/epeople-registry.component.spec.ts
deleteEPerson now shows the self-delete notification when isCurrentUser(ePerson) is true or isSelfDeletionError is true; a new test verifies this using a deferred failure response with unusable error content.
Eperson-form self-delete branch and tests
src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts, src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts
delete() applies the same combined isCurrentUser/isSelfDeletionError condition, with a corresponding new spec test.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: milanmajchrak

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and clearly describes the main change: fixing the misleading self-delete notification.
Description check ✅ Passed The description covers the problem, root cause, fix, and test plan, which satisfies the template's required content.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/app/access-control/epeople-registry/eperson-delete-guard.service.ts (1)

89-91: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider centralizing the self-delete OR-condition in the guard.

isCurrentUser(...) || isSelfDeletionError(...) is duplicated identically in both EPeopleRegistryComponent and EPersonFormComponent. Adding a single combined method here would remove the duplication and prevent the two call sites from drifting apart in a future change.

♻️ Proposed centralized helper
   isSelfDeletionError(restResponse: RemoteData<NoContent> | null): boolean {
     return restResponse?.statusCode === 400 && restResponse?.errorMessage?.toLowerCase().includes('cannot delete yourself');
   }
 
+  /**
+   * Whether the friendly self-delete notification should be shown for this delete attempt,
+   * combining the client-side identity check with the best-effort backend error-message check.
+   */
+  shouldShowSelfDeleteNotification(ePerson: EPerson, currentAuthenticatedUserId: string, restResponse: RemoteData<NoContent> | null): boolean {
+    return this.isCurrentUser(ePerson, currentAuthenticatedUserId) || this.isSelfDeletionError(restResponse);
+  }
+
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/access-control/epeople-registry/eperson-delete-guard.service.ts`
around lines 89 - 91, The self-delete check is duplicated as isCurrentUser(...)
|| isSelfDeletionError(...) in both EPeopleRegistryComponent and
EPersonFormComponent. Add a single combined helper in EpersonDeleteGuardService,
рядом with isSelfDeletionError, that encapsulates both conditions and use that
method from both call sites to keep the logic centralized and prevent drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/app/access-control/epeople-registry/eperson-delete-guard.service.ts`:
- Around line 89-91: The self-delete check is duplicated as isCurrentUser(...)
|| isSelfDeletionError(...) in both EPeopleRegistryComponent and
EPersonFormComponent. Add a single combined helper in EpersonDeleteGuardService,
рядом with isSelfDeletionError, that encapsulates both conditions and use that
method from both call sites to keep the logic centralized and prevent drift.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c0df45b1-046e-4099-badf-a6993f6db406

📥 Commits

Reviewing files that changed from the base of the PR and between 1321b8a and 728c874.

📒 Files selected for processing (5)
  • src/app/access-control/epeople-registry/epeople-registry.component.spec.ts
  • src/app/access-control/epeople-registry/epeople-registry.component.ts
  • src/app/access-control/epeople-registry/eperson-delete-guard.service.ts
  • src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts
  • src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant